﻿Imports System.Windows.Forms.VisualStyles

Friend Class FloorItems

    Public Structure MirFloorItem
        Dim I As FloorItem
        Dim ownerTimeout As Long
    End Structure

    'dictates the max spread of items before they pile up, MUST BE AN ODD NUMBER
    Private Const MAX_ITEM_SPREAD = 9

    Private mParentMap As String
    Private lstItems As List(Of MirFloorItem)
    Private objItems As Object

    Private ItemCount(,) As Integer

    Public Sub New(ByRef parentmap As String, ByVal w As Integer, ByVal h As Integer)

        mParentMap = parentmap
        lstItems = New List(Of MirFloorItem)
        objItems = New Object

        Dim m As MirMap = GetMapFromName(parentmap)

        ReDim ItemCount(w, h)

    End Sub

    Public Sub AddToken(conn As Connection, looks As Integer, caption As String)

        Dim item As MirFloorItem

        item.I.INT_ID = -1
        item.I.STR_NAME = caption
        item.I.BYTE_ITEMCLASS = ItemClass.Rare
        item.I.INT_LOOKS = looks
        item.I.INT_COUNT = 1
        item.I.INT2_WEIGHT = 1

        Dim m As MirMap = GetMapFromName(mParentMap)

        Dim pkt As Packet

        Dim x As Integer = conn.PositionInfo.INT2_X
        Dim y As Integer = conn.PositionInfo.INT2_Y

        item.I.INT2_X = x
        item.I.INT2_Y = y

        item.ownerTimeout = Long.MaxValue

        pkt.PacketType = GamePacketType.FloorItemAddUpdate
        pkt.PacketOpCode = PacketOpCode.Notify
        pkt.Username = DefaultUsername

        SyncLock objItems
            lstItems.Add(item)
            ItemCount(x, y) += 1
        End SyncLock

        SendToLocalPlayers(x, y, m, pkt, item.I)

    End Sub

    Public Sub Add(ByVal id As Int64, ByVal x As Int32, ByVal y As Int32, Optional ByRef conn As Connection = Nothing, Optional freepickup As Boolean = False)

        Dim item As MirFloorItem
        Dim sSql As String

        If conn Is Nothing Then
            sSql = "SELECT a.ID_ITEM, a.INT_COUNT, b.INT_LOOKS, b.BYTE_ITEMCLASS, b.STR_NAME, b.INT2_WEIGHT FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE a.ID_ITEM=" & id & ";"
        Else
            sSql = "SELECT a.ID_ITEM, a.INT_COUNT, b.INT_LOOKS, b.BYTE_ITEMCLASS, b.STR_NAME, b.INT2_WEIGHT FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE a.ID_ITEM=" & id & " AND a.ID_CHARACTER=" & conn.CharacterID & ";"
        End If

        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then Exit Sub
        If row.Count = 0 Then Exit Sub

        item.I.INT_ID = row("ID_ITEM")
        item.I.STR_NAME = row("STR_NAME")
        item.I.BYTE_ITEMCLASS = row("BYTE_ITEMCLASS")
        item.I.INT_LOOKS = row("INT_LOOKS")
        item.I.INT_COUNT = row("INT_COUNT")
        item.I.INT2_WEIGHT = row("INT2_WEIGHT")
        sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Floor & " WHERE ID_ITEM= " & id & ";"
        DB.GameDB.ExecuteNonQuery(sSql)

        Dim tx As Integer = x - 1, ty As Integer = y - 1
        Dim d As Direction = Direction.E, c As Integer = 3, i As Integer = 0
        Dim ic As Integer

        Dim m As MirMap = GetMapFromName(mParentMap)

        Dim pkt As Packet

        SyncLock objItems

            Do

                tx = x - 1
                ty = y - 1
                d = Direction.E
                c = 2
                i = 0

                Do

                    i += 1

                    Select Case d

                        Case Direction.N
                            ty -= 1
                        Case Direction.W
                            tx -= 1
                            If c = i Then
                                d = Direction.N
                                i = 0
                            End If
                        Case Direction.S
                            ty += 1
                            If c = i Then
                                d = Direction.W
                                i = 0
                            End If
                        Case Direction.E
                            tx += 1
                            If c = i Then
                                d = Direction.S
                                i = 0
                            End If

                    End Select

                    If m.isPassable(tx, ty) And ItemCount(tx, ty) = ic Then GoTo foundspace

                    If d = Direction.N And c = i Then
                        d = Direction.E
                        i = 0
                        c += 2
                        ty -= 1
                    End If

                Loop Until d = Direction.E And c = MAX_ITEM_SPREAD

                ic += 1

            Loop Until ic = 7

            tx = x
            ty = y

foundspace:

            item.I.INT2_X = tx
            item.I.INT2_Y = ty

            pkt.PacketType = GamePacketType.FloorItemAddUpdate
            pkt.PacketOpCode = PacketOpCode.Notify
            pkt.Username = DefaultUsername

            If freepickup Then
                item.ownerTimeout = DateTime.Now.Ticks
            Else
                item.ownerTimeout = DateTime.Now.Ticks + Constants.TimeOut_FloorItemOwnership
            End If

            lstItems.Add(item)
            ItemCount(tx, ty) += 1

        End SyncLock

        SendToLocalPlayers(tx, ty, m, pkt, item.I)

    End Sub

    Public Sub PickupItem(ByVal id As Int64, ByRef conn As Connection)

        Dim tmpitem As MirFloorItem

        SyncLock objItems

            For Each item As MirFloorItem In lstItems

                If item.I.INT_ID = id Then

                    'get the owner of the item
                    Dim sSql As String = "SELECT ID_CHARACTER FROM TBL_ITEMS WHERE ID_ITEM=" & id & ";"
                    'execute the sql
                    Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

                    If row Is Nothing Then Exit Sub
                    If row.Count = 0 Then Exit Sub

                    'if character is the owner or timeout has expired
                    If row("ID_CHARACTER") = conn.CharacterID Or item.ownerTimeout < DateTime.Now.Ticks Then

                        If Not row("ID_CHARACTER") = conn.CharacterID Then

                            sSql = "UPDATE TBL_ITEMS SET ID_CHARACTER=" & conn.CharacterID & " WHERE ID_ITEM=" & id & ";"
                            DB.GameDB.ExecuteNonQuery(sSql)

                        End If

                        'get the MirFloorItem
                        tmpitem = item
                        'remove from the list
                        lstItems.Remove(item)

                    End If

                    Exit For

                End If

            Next

        End SyncLock

        If tmpitem.I.INT_ID = id Then

            'Packet header for floor item removal
            Dim pkt As Packet
            pkt.PacketType = GamePacketType.FloorItemRemoveUpdate
            pkt.PacketOpCode = PacketOpCode.Notify
            pkt.Username = DefaultUsername

            'Send floor item removal packet to everyone who is nearby
            SendToLocalPlayers(tmpitem.I.INT2_X, tmpitem.I.INT2_Y, GetMapFromConn(conn), pkt, id)

            'update the item location
            Dim loc As ItemLocationInfo
            loc.INT_ID = tmpitem.I.INT_ID
            loc.location = ItemLocation.Inventory
            ChangeItemLocation(loc, conn)

            'load the item into the characters inventory
            LoadNewItem(conn, id)

        End If

    End Sub

    Public Sub UpdatePlayerDueToMove(ByVal conn As Connection, ByVal movedir As Point)

        Dim addreply As Packet
        addreply.PacketType = GamePacketType.FloorItemAddUpdate
        addreply.PacketOpCode = PacketOpCode.Notify
        addreply.Username = conn.Username

        Dim remreply As Packet
        remreply.PacketType = GamePacketType.FloorItemRemoveUpdate
        remreply.PacketOpCode = PacketOpCode.Notify
        remreply.Username = conn.Username

        Dim addstruct As FloorItem
        Dim remstruct As Int64

        SyncLock objItems

            For Each item As MirFloorItem In lstItems

                If mPlayers.IsEnteringPlayArea(movedir, conn.PositionInfo.INT2_X, conn.PositionInfo.INT2_Y, item.I.INT2_X, item.I.INT2_Y) Then
                    addstruct = item.I

                    Socket.SockServer.SendData(Protocol.MakePacket(addreply, addstruct, conn.Crypto), conn.Index)

                ElseIf mPlayers.IsLeavingPlayArea(movedir, conn.PositionInfo.INT2_X, conn.PositionInfo.INT2_Y, item.I.INT2_X, item.I.INT2_Y) Then

                    remstruct = item.I.INT_ID

                    Socket.SockServer.SendData(Protocol.MakePacket(remreply, remstruct, conn.Crypto), conn.Index)

                End If

            Next

        End SyncLock

    End Sub

    Public Sub UpdatePlayer(ByRef Conn As Connection, ByVal x As Integer, ByVal y As Integer)

        Dim reply As Packet
        reply.PacketType = GamePacketType.FloorItemAddUpdate
        reply.PacketOpCode = PacketOpCode.Notify
        reply.Username = Conn.Username

        SyncLock objItems

            For Each item As MirFloorItem In lstItems
                If item.I.INT2_X >= x - Constants.UpdateAreaX And item.I.INT2_X <= x + Constants.UpdateAreaX Then
                    If item.I.INT2_Y >= y - Constants.UpdateAreaY And item.I.INT2_Y <= y + Constants.UpdateAreaY Then

                        Socket.SockServer.SendData(Protocol.MakePacket(reply, item.I, Conn.Crypto), Conn.Index)
                        System.Windows.Forms.Application.DoEvents()

                    End If
                End If
            Next

        End SyncLock

    End Sub

    Public Sub DoDrop(ByVal item As DropItemRequest, ByVal conn As Connection)

        Dim sSql As String = "SELECT * FROM TBL_ITEMS WHERE ID_ITEM=" & item.INT_ID & " AND ID_CHARACTER=" & conn.CharacterID & ";"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then Exit Sub

        If row.Count > 0 Then

            Dim iteminfo As ItemInfo = ItemInfoFromItemID(item.INT_ID)
            conn.PlayerWeight.INT4_BAGWEIGHT -= iteminfo.Base.INT2_WEIGHT * iteminfo.INT_COUNT

            UpdatePlayerWeights(conn)

            Add(item.INT_ID, conn.PositionInfo.INT2_X, conn.PositionInfo.INT2_Y, conn, True)

        End If

    End Sub

End Class

Module mItems

    Public Function GetItemShape(ByVal itemid As Int64) As Integer

        Dim sSql As String = "SELECT ID_ITEMBASE FROM TBL_ITEMS WHERE ID_ITEM=" & itemid & ";"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then Exit Function

        If row.Count = 0 Then
            Return 0
        Else

            sSql = "SELECT INT_SHAPE FROM TBL_ITEMBASE WHERE ID_ITEMBASE=" & row("ID_ITEMBASE") & ";"
            row = DB.GameDB.ExecuteQueryFirstRecord(sSql)

            If row Is Nothing Then Exit Function

            If row.Count = 0 Then
                Return 0
            Else
                Return row("INT_SHAPE")
            End If

        End If

    End Function

    Public Function GetItemAlphaCol(ByVal itemid As Int64) As Integer

        Dim sSql As String = "SELECT INT_ALPHACOL FROM TBL_ITEMS WHERE ID_ITEM=" & itemid & ";"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then Exit Function

        If row.Count = 0 Then
            Return 0
        Else
            Return row("INT_ALPHACOL")
        End If

    End Function

    Public Function CreateNewItem(ByVal sItemName As String, ByVal idChar As Integer, Optional ByVal count As Integer = 1, Optional ByVal location As ItemLocation = ItemLocation.Inventory, Optional maxdura As Boolean = False) As Int64

        'TODO: Add random stats chance to items

        Dim sSql As String = "SELECT ID_ITEMBASE, BYTE_TYPE FROM TBL_ITEMBASE WHERE STR_NAME='" & sItemName & "';"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then Return 0

        If row.Count > 0 Then

            Dim alphacol As Integer

            If row("BYTE_TYPE") = ItemType.MArmor Or row("BYTE_TYPE") = ItemType.FArmor Then
                alphacol = GenerateArmorColor()
            Else
                alphacol = -1
            End If

            Dim dura As Long
            If maxdura Then
                dura = CLng(ItemBaseInfoFromItemBaseID(row("ID_ITEMBASE")).Stats.INT_MAX_DURABILITY * 1000)
            Else
                dura = CLng((ItemBaseInfoFromItemBaseID(row("ID_ITEMBASE")).Stats.INT_MAX_DURABILITY * 1000) * Rnd())
            End If


            sSql = "INSERT INTO TBL_ITEMS (ID_ITEMBASE, ID_CHARACTER, INT_ALPHACOL, BYTE_LOCATION, INT_COUNT, INT2_ITEMLEVEL, INT_ITEMEXP, INT2_ADD_MIN_AC, INT2_ADD_MIN_MAC, INT2_ADD_MIN_DC, INT2_ADD_MIN_MC, INT2_ADD_MIN_SC, " & _
                    "INT2_ADD_MAX_HP, INT2_ADD_MAX_MP, INT2_ADD_MAX_AC, INT2_ADD_MAX_MAC, INT2_ADD_MAX_DC, INT2_ADD_MAX_MC, INT2_ADD_MAX_SC, INT2_ADD_MAX_WEIGHT, INT2_ADD_MAX_HANDWEIGHT, INT2_ADD_MAX_WEARWEIGHT, " & _
                    "INT2_ADD_ELEMC_FIRE, INT2_ADD_ELEMC_ICE, INT2_ADD_ELEMC_LIGHT, INT2_ADD_ELEMC_WIND, INT2_ADD_ELEMC_HOLY, INT2_ADD_ELEMC_DARK, INT2_ADD_ELEMC_PHANTOM, INT2_ADD_ELEMAC_FIRE, INT2_ADD_ELEMAC_ICE, " & _
                    "INT2_ADD_ELEMAC_LIGHT, INT2_ADD_ELEMAC_WIND, INT2_ADD_ELEMAC_HOLY, INT2_ADD_ELEMAC_DARK, INT2_ADD_ELEMAC_PHANTOM, INT1_ADD_ACCURACY, INT1_ADD_AGILITY, INT1_ADD_VELOCITY, INT_ADD_MAX_DURABILITY, " & _
                    "INT_DURABILITY, INT1_ADD_STRENGTH, INT1_ADD_LUCK)" & _
                    "VALUES (" & row("ID_ITEMBASE") & "," & idChar & "," & alphacol & "," & Int(location) & "," & count & ",1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0," & dura & ",0,0); " & _
                    "SELECT SCOPE_IDENTITY();"

            row = DB.GameDB.ExecuteQueryFirstRecord(sSql)
            If row Is Nothing Then Return 0
            If row.Count = 0 Then Return 0

            Return row(1)

        End If

        Return 0

    End Function

    Private Function GenerateArmorColor() As Integer

        Dim r As Integer = CInt(Rnd() * 9) + 1
        Dim col As Integer

        'TODO: Add more armor colors (now have 10)

        Select Case r
            Case 1
                col = System.Drawing.Color.White.ToArgb

            Case 2
                col = System.Drawing.Color.Red.ToArgb

            Case 3
                col = System.Drawing.Color.Black.ToArgb

            Case 4
                col = System.Drawing.Color.GreenYellow.ToArgb

            Case 5
                col = System.Drawing.Color.BlueViolet.ToArgb

            Case 6
                col = System.Drawing.Color.SteelBlue.ToArgb

            Case 7
                col = System.Drawing.Color.Crimson.ToArgb

            Case 8
                col = System.Drawing.Color.LightGreen.ToArgb

            Case 9
                col = System.Drawing.Color.Honeydew.ToArgb

            Case 10
                col = System.Drawing.Color.LightPink.ToArgb


        End Select

        Return col

    End Function

    Public Sub UnEquipItem(ByVal itemid As Int64, ByRef Conn As Connection, Optional ByVal dontsendstatupdate As Boolean = False, Optional ByVal dontsendaddtoinventory As Boolean = False)

        Dim struct As ItemInfo

        struct = ItemInfoFromItemID(itemid)

        If Not struct.INT_ID = 0 Then

            RemoveItemStatsFromConn(Conn, struct)

            Dim slot As ItemLocation = GetItemLocation(itemid)

            Select Case slot

                Case ItemLocation.EquipArmor
                    Conn.PlayerInfo.ShapeInfo.INT_ARMORSHAPE = 0

                Case ItemLocation.EquipHelmet
                    Conn.PlayerInfo.ShapeInfo.INT_HEADSHAPE = -1

                Case ItemLocation.EquipWeapon
                    Conn.PlayerInfo.ShapeInfo.INT_WEAPONSHAPE = -1

                Case ItemLocation.EquipTorch
                    'TODO: Torch ref (unequip)
                    Conn.PlayerInfo.ShapeInfo.BOOL_HASLIGHT = False

            End Select

            If Not dontsendstatupdate Then
                UpdatePlayerStats(Conn)
                UpdatePlayersCharShape(Conn)
            End If

            If Not dontsendaddtoinventory Then

                Dim pkt As Packet
                pkt.PacketType = GamePacketType.AddToInventory
                pkt.PacketOpCode = PacketOpCode.Notify
                pkt.Username = Conn.Username
                Socket.SockServer.SendData(Protocol.MakePacket(pkt, struct, Conn.Crypto), Conn.Index)

            End If

            If slot = ItemLocation.EquipTorch Or slot = ItemLocation.EquipWeapon Then
                Conn.PlayerWeight.INT4_HANDWEIGHT -= struct.Base.INT2_WEIGHT
            Else
                Conn.PlayerWeight.INT4_WEARWEIGHT -= struct.Base.INT2_WEIGHT
            End If


            Conn.PlayerWeight.INT4_BAGWEIGHT += struct.Base.INT2_WEIGHT
            UpdatePlayerWeights(Conn)

        End If

        SetItemLocation(Conn, itemid, ItemLocation.Inventory)

    End Sub

    Public Sub EquipItem(ByVal idItem As Int64, ByVal slot As ItemLocation, ByRef Conn As Connection, Optional ByVal dontupdatedb As Boolean = False, Optional skipweight As Boolean = False)

        Dim struct As ItemInfo

        If Not dontupdatedb Then

            Dim sSql As String = "SELECT a.ID_ITEM, b.INT2_WEIGHT FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE a.ID_CHARACTER=" & Conn.CharacterID & " AND a.BYTE_LOCATION=" & slot & ";"
            Dim row As ArrayList = DB.GameDB.ExecuteQuery(sSql)

            If Not row Is Nothing Then

                If row.Count > 0 Then

                    For i As Integer = 0 To row.Count - 1

                        If row(i)("ID_ITEM") <> idItem Then
                            UnEquipItem(row(i)("ID_ITEM"), Conn, True)
                        Else
                            Exit Sub
                        End If

                    Next

                End If

            End If

            SetItemLocation(Conn, idItem, slot)

        End If

        struct = ItemInfoFromItemID(idItem)

        If Not struct.INT_ID = 0 Then

            AddItemStatsToConn(Conn, struct)

            Select Case slot

                Case ItemLocation.EquipArmor
                    Conn.PlayerInfo.ShapeInfo.INT_ARMORSHAPE = struct.Base.INT_SHAPE
                    Conn.PlayerInfo.ShapeInfo.INT_ARMORCOL = struct.INT_ALPHACOL

                Case ItemLocation.EquipHelmet
                    Conn.PlayerInfo.ShapeInfo.INT_HEADSHAPE = struct.Base.INT_SHAPE

                Case ItemLocation.EquipWeapon
                    Conn.PlayerInfo.ShapeInfo.INT_WEAPONSHAPE = struct.Base.INT_SHAPE

                Case ItemLocation.EquipTorch
                    'TODO: Torch ref (equip)
                    Conn.PlayerInfo.ShapeInfo.BOOL_HASLIGHT = True

            End Select

            Dim pkt As Packet
            pkt.PacketType = GamePacketType.EquipItem
            pkt.PacketOpCode = PacketOpCode.Notify
            pkt.Username = Conn.Username

            Dim struct2 As ItemSlotInfo

            struct2.slot = slot
            struct2.item = struct

            System.Windows.Forms.Application.DoEvents()

            Socket.SockServer.SendData(Protocol.MakePacket(pkt, struct2, Conn.Crypto), Conn.Index)

            If Not dontupdatedb Then
                UpdatePlayerStats(Conn)
                UpdatePlayersCharShape(Conn)
            End If

            If Not skipweight Then
                Conn.PlayerWeight.INT4_BAGWEIGHT -= struct.Base.INT2_WEIGHT
            End If

            If slot = ItemLocation.EquipTorch Or slot = ItemLocation.EquipWeapon Then
                Conn.PlayerWeight.INT4_HANDWEIGHT += struct.Base.INT2_WEIGHT
            Else
                Conn.PlayerWeight.INT4_WEARWEIGHT += struct.Base.INT2_WEIGHT
            End If

            System.Windows.Forms.Application.DoEvents()
            UpdatePlayerWeights(Conn)

        End If

    End Sub

    Public Sub LoadNewItem(ByRef Conn As Connection, ByVal id As Int64)


        Dim struct As ItemInfo

        Dim pkt As Packet
        pkt.PacketType = GamePacketType.AddToInventory
        pkt.PacketOpCode = PacketOpCode.Notify
        pkt.Username = Conn.Username


        struct = ItemInfoFromItemID(id)

        If Not struct.INT_ID = 0 Then

            Socket.SockServer.SendData(Protocol.MakePacket(pkt, struct, Conn.Crypto), Conn.Index)

            Conn.PlayerWeight.INT4_BAGWEIGHT += struct.Base.INT2_WEIGHT * struct.INT_COUNT
            UpdatePlayerWeights(Conn)

        End If


    End Sub

    Public Function ItemBaseInfoFromItemBaseID(id As Long) As ItemBaseInfo

        Dim sSql As String
        sSql = "SELECT * FROM TBL_ITEMBASE WHERE ID_ITEMBASE=" & id & ";"

        Dim col As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        Dim item As ItemBaseInfo

        item.INT_ID_ITEMBASE = col("ID_ITEMBASE")
        item.STR_NAME = col("STR_NAME")
        item.BYTE_TYPE = col("BYTE_TYPE")
        item.INT_SHAPE = col("INT_SHAPE")
        item.INT_LOOKS = col("INT_LOOKS")
        item.BOOL_STACKS = col("BOOL_STACKS")
        item.INT8_COST = col("INT8_COST")
        item.INT2_LEVELREQ = col("INT2_LEVELREQ")
        item.INT2_WEIGHT = col("INT2_WEIGHT")
        item.BYTE_ITEMCLASS = col("BYTE_ITEMCLASS")
        item.INT1_EXPBONUS = col("INT1_EXPBONUS")

        item.Stats.INT2_MIN_AC = col("INT2_MIN_AC")
        item.Stats.INT2_MIN_MAC = col("INT2_MIN_MAC")
        item.Stats.INT2_MIN_DC = col("INT2_MIN_DC")
        item.Stats.INT2_MIN_MC = col("INT2_MIN_MC")
        item.Stats.INT2_MIN_SC = col("INT2_MIN_SC")
        item.Stats.INT2_MAX_HP = col("INT2_MAX_HP")
        item.Stats.INT2_MAX_MP = col("INT2_MAX_MP")
        item.Stats.INT2_MAX_AC = col("INT2_MAX_AC")
        item.Stats.INT2_MAX_MAC = col("INT2_MAX_MAC")
        item.Stats.INT2_MAX_DC = col("INT2_MAX_DC")
        item.Stats.INT2_MAX_MC = col("INT2_MAX_MC")
        item.Stats.INT2_MAX_SC = col("INT2_MAX_SC")
        item.Stats.INT2_ELEMC_FIRE = col("INT2_ELEMC_FIRE")
        item.Stats.INT2_ELEMC_ICE = col("INT2_ELEMC_ICE")
        item.Stats.INT2_ELEMC_LIGHT = col("INT2_ELEMC_LIGHT")
        item.Stats.INT2_ELEMC_WIND = col("INT2_ELEMC_WIND")
        item.Stats.INT2_ELEMC_HOLY = col("INT2_ELEMC_HOLY")
        item.Stats.INT2_ELEMC_DARK = col("INT2_ELEMC_DARK")
        item.Stats.INT2_ELEMC_PHANTOM = col("INT2_ELEMC_PHANTOM")
        item.Stats.INT2_ELEMAC_FIRE = col("INT2_ELEMAC_FIRE")
        item.Stats.INT2_ELEMAC_ICE = col("INT2_ELEMAC_ICE")
        item.Stats.INT2_ELEMAC_LIGHT = col("INT2_ELEMAC_LIGHT")
        item.Stats.INT2_ELEMAC_WIND = col("INT2_ELEMAC_WIND")
        item.Stats.INT2_ELEMAC_HOLY = col("INT2_ELEMAC_HOLY")
        item.Stats.INT2_ELEMAC_DARK = col("INT2_ELEMAC_DARK")
        item.Stats.INT2_ELEMAC_PHANTOM = col("INT2_ELEMAC_PHANTOM")
        item.Stats.INT1_ACCURACY = col("INT1_ACCURACY")
        item.Stats.INT1_AGILITY = col("INT1_AGILITY")
        item.Stats.INT1_VELOCITY = col("INT1_VELOCITY")
        item.Stats.INT_MAX_DURABILITY = col("INT_MAX_DURABILITY")
        item.Stats.INT1_STRENGTH = col("INT1_STRENGTH")
        item.Stats.INT1_LUCK = col("INT1_LUCK")

        Return item

    End Function

    Public Function GetItemLocation(id As Long) As Protocol.ItemLocation

        Dim sSql As String = "SELECT BYTE_LOCATION FROM TBL_ITEMS WHERE ID_ITEM=" & id & ";"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then
            Return ItemLocation.Deleted
        Else
            If row.Count > 0 Then
                Return CType(row("BYTE_LOCATION"), Protocol.ItemLocation)
            Else
                Return ItemLocation.Deleted
            End If
        End If
    End Function

    Public Sub SetItemLocation(ByRef conn As Connection, id As Long, loc As Protocol.ItemLocation)

        Dim sSql As String = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & loc & " WHERE ID_ITEM=" & id & " AND ID_CHARACTER=" & conn.CharacterID & ";"
        DB.GameDB.ExecuteNonQuery(sSql)

    End Sub

    Public Function ItemInfoFromItemID(id As Long) As ItemInfo

        Dim sSql As String = "SELECT * FROM TBL_ITEMBASE a JOIN TBL_ITEMS b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE b.ID_ITEM=" & id & ";"
        Dim col As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        Dim item As ItemInfo

        item.INT_ID = col("ID_ITEM")
        item.INT_COUNT = col("INT_COUNT")
        item.INT_ALPHACOL = col("INT_ALPHACOL")
        item.INT_DURABILITY = col("INT_DURABILITY")
        item.INT2_ITEMLEVEL = col("INT2_ITEMLEVEL")
        item.INT_ITEMEXP = col("INT_ITEMEXP")
        item.AddedStats.INT2_MIN_AC = col("INT2_ADD_MIN_AC")
        item.AddedStats.INT2_MIN_MAC = col("INT2_ADD_MIN_MAC")
        item.AddedStats.INT2_MIN_DC = col("INT2_ADD_MIN_DC")
        item.AddedStats.INT2_MIN_MC = col("INT2_ADD_MIN_MC")
        item.AddedStats.INT2_MIN_SC = col("INT2_ADD_MIN_SC")
        item.AddedStats.INT2_MAX_HP = col("INT2_ADD_MAX_HP")
        item.AddedStats.INT2_MAX_MP = col("INT2_ADD_MAX_MP")
        item.AddedStats.INT2_MAX_AC = col("INT2_ADD_MAX_AC")
        item.AddedStats.INT2_MAX_MAC = col("INT2_ADD_MAX_MAC")
        item.AddedStats.INT2_MAX_DC = col("INT2_ADD_MAX_DC")
        item.AddedStats.INT2_MAX_MC = col("INT2_ADD_MAX_MC")
        item.AddedStats.INT2_MAX_SC = col("INT2_ADD_MAX_SC")
        item.AddedStats.INT2_MAX_WEIGHT = col("INT2_ADD_MAX_WEIGHT")
        item.AddedStats.INT2_MAX_HANDWEIGHT = col("INT2_ADD_MAX_HANDWEIGHT")
        item.AddedStats.INT2_MAX_WEARWEIGHT = col("INT2_ADD_MAX_WEARWEIGHT")
        item.AddedStats.INT2_ELEMC_FIRE = col("INT2_ADD_ELEMC_FIRE")
        item.AddedStats.INT2_ELEMC_ICE = col("INT2_ADD_ELEMC_ICE")
        item.AddedStats.INT2_ELEMC_LIGHT = col("INT2_ADD_ELEMC_LIGHT")
        item.AddedStats.INT2_ELEMC_WIND = col("INT2_ADD_ELEMC_WIND")
        item.AddedStats.INT2_ELEMC_HOLY = col("INT2_ADD_ELEMC_HOLY")
        item.AddedStats.INT2_ELEMC_DARK = col("INT2_ADD_ELEMC_DARK")
        item.AddedStats.INT2_ELEMC_PHANTOM = col("INT2_ADD_ELEMC_PHANTOM")
        item.AddedStats.INT2_ELEMAC_FIRE = col("INT2_ADD_ELEMAC_FIRE")
        item.AddedStats.INT2_ELEMAC_ICE = col("INT2_ADD_ELEMAC_ICE")
        item.AddedStats.INT2_ELEMAC_LIGHT = col("INT2_ADD_ELEMAC_LIGHT")
        item.AddedStats.INT2_ELEMAC_WIND = col("INT2_ADD_ELEMAC_WIND")
        item.AddedStats.INT2_ELEMAC_HOLY = col("INT2_ADD_ELEMAC_HOLY")
        item.AddedStats.INT2_ELEMAC_DARK = col("INT2_ADD_ELEMAC_DARK")
        item.AddedStats.INT2_ELEMAC_PHANTOM = col("INT2_ADD_ELEMAC_PHANTOM")
        item.AddedStats.INT1_ACCURACY = col("INT1_ADD_ACCURACY")
        item.AddedStats.INT1_AGILITY = col("INT1_ADD_AGILITY")
        item.AddedStats.INT1_VELOCITY = col("INT1_ADD_VELOCITY")
        item.AddedStats.INT_MAX_DURABILITY = col("INT_ADD_MAX_DURABILITY")
        item.AddedStats.INT1_STRENGTH = col("INT1_ADD_STRENGTH")
        item.AddedStats.INT1_LUCK = col("INT1_ADD_LUCK")

        item.Base = ItemBaseInfoFromItemBaseID(col("ID_ITEMBASE"))

        If item.Base.Stats.INT_MAX_DURABILITY > 0 Then
            item.INT_REALCOST = CLng(item.Base.INT8_COST * (item.INT_DURABILITY / (item.Base.Stats.INT_MAX_DURABILITY * 1000)))
        Else
            item.INT_REALCOST = item.Base.INT8_COST
        End If

        Return item

    End Function

    Public Sub ChangeItemLocation(ByVal struct As ItemLocationInfo, ByRef Conn As Connection, Optional skipbagweight As Boolean = False)

        Dim sSql As String
        Dim col As Collection
        Dim loc As ItemLocation = struct.location

        sSql = "SELECT BYTE_LOCATION FROM TBL_ITEMS WHERE ID_CHARACTER=" & Conn.CharacterID & " AND ID_ITEM=" & struct.INT_ID & ";"
        col = DB.GameDB.ExecuteQueryFirstRecord(sSql)
        If col Is Nothing Then
            Exit Sub
        Else
            If col.Count > 0 Then
                If col("BYTE_LOCATION") = loc Then
                    Exit Sub
                End If
            Else
                Exit Sub
            End If
        End If

        If loc = ItemLocation.EquipArmor Or loc = ItemLocation.EquipHelmet Or loc = ItemLocation.EquipHorseArmor Or loc = ItemLocation.EquipLeftBracer Or loc = ItemLocation.EquipLeftRing Or loc = ItemLocation.EquipNecklace Or loc = ItemLocation.EquipRightBracer Or loc = ItemLocation.EquipRightRing Or loc = ItemLocation.EquipShoes Or loc = ItemLocation.EquipTalisman Or loc = ItemLocation.EquipTorch Or loc = ItemLocation.EquipTrinket Or loc = ItemLocation.EquipWeapon Then
            sSql = "SELECT a.ID_ITEM FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE a.ID_CHARACTER=" & Conn.CharacterID & " AND a.BYTE_LOCATION=" & struct.location & ";"
            Dim arr As ArrayList = DB.GameDB.ExecuteQuery(sSql)
            If Not arr Is Nothing Then
                If arr.Count > 0 Then
                    For i As Integer = 0 To arr.Count - 1
                        If arr(i)("ID_ITEM") <> struct.INT_ID Then
                            UnEquipItem(arr(i)("ID_ITEM"), Conn, )
                        End If
                    Next
                End If
            End If

        End If

        sSql = "SELECT BYTE_LOCATION FROM TBL_ITEMS WHERE ID_ITEM=" & struct.INT_ID & " AND ID_CHARACTER=" & Conn.CharacterID & ";"
        col = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If col Is Nothing Then Exit Sub

        If col.Count > 0 Then

            loc = col("BYTE_LOCATION")
            If loc = ItemLocation.EquipArmor Or loc = ItemLocation.EquipHelmet Or loc = ItemLocation.EquipHorseArmor Or loc = ItemLocation.EquipLeftBracer Or loc = ItemLocation.EquipLeftRing Or loc = ItemLocation.EquipNecklace Or loc = ItemLocation.EquipRightBracer Or loc = ItemLocation.EquipRightRing Or loc = ItemLocation.EquipShoes Or loc = ItemLocation.EquipTalisman Or loc = ItemLocation.EquipTorch Or loc = ItemLocation.EquipTrinket Or loc = ItemLocation.EquipWeapon Then
                If loc <> struct.location Then
                    UnEquipItem(struct.INT_ID, Conn, True, True)
                End If
            End If

            loc = struct.location
            If loc = ItemLocation.EquipArmor Or loc = ItemLocation.EquipHelmet Or loc = ItemLocation.EquipHorseArmor Or loc = ItemLocation.EquipLeftBracer Or loc = ItemLocation.EquipLeftRing Or loc = ItemLocation.EquipNecklace Or loc = ItemLocation.EquipRightBracer Or loc = ItemLocation.EquipRightRing Or loc = ItemLocation.EquipShoes Or loc = ItemLocation.EquipTalisman Or loc = ItemLocation.EquipTorch Or loc = ItemLocation.EquipTrinket Or loc = ItemLocation.EquipWeapon Then
                EquipItem(struct.INT_ID, loc, Conn)
            Else
                UpdatePlayerStats(Conn)
                UpdatePlayersCharShape(Conn)

                sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & struct.location & " WHERE ID_ITEM=" & struct.INT_ID & " AND ID_CHARACTER=" & Conn.CharacterID & ";"
                DB.GameDB.ExecuteNonQuery(sSql)

            End If

            System.Windows.Forms.Application.DoEvents()

        End If

    End Sub

    Public Function DoesItemStack(itemname As String) As Boolean

        Dim sSql As String = "SELECT BOOL_STACKS FROM TBL_ITEMBASE WHERE STR_NAME='" & itemname & "';"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then Return False
        If row.Count = 0 Then Return False
        If row("BOOL_STACKS") = True Then
            Return True
        Else
            Return False
        End If

    End Function

    Public Sub SplitStack(split As SplitStackRequest, conn As Connection)

        'retrieve item name and original stack count
        Dim sSql As String = "SELECT a.STR_NAME, b.INT_COUNT FROM TBL_ITEMBASE a JOIN TBL_ITEMS b ON b.ID_ITEMBASE = a.ID_ITEMBASE WHERE b.ID_ITEM='" & split.INT_ID & "' AND b.BYTE_LOCATION='" & ItemLocation.Inventory & "' AND a.BOOL_STACKS='True';"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        'if no rows then packet was errornous
        If row Is Nothing Then Exit Sub
        If row.Count = 0 Then Exit Sub

        'check that there are enough items in the stack to make the requested stack size
        If row("INT_COUNT") > split.INT_STACKSIZE Then

            'calculate the required sizes for the 2 new stacks
            Dim stacksizeA As Integer = row("INT_COUNT") - split.INT_STACKSIZE
            Dim stacksizeB As Integer = split.INT_STACKSIZE

            'delete the old stack in DB
            sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION='" & ItemLocation.Deleted & "' WHERE ID_ITEM='" & split.INT_ID & "';"
            DB.GameDB.ExecuteNonQuery(sSql)
            'send RemoveItem packet for the old stack
            RemoveItem(split.INT_ID, conn)

            System.Windows.Forms.Application.DoEvents()

            'create 2 new stacks
            Dim id As Int64 = CreateNewItem(row("STR_NAME"), conn.CharacterID, stacksizeA)
            Dim id2 As Int64 = CreateNewItem(row("STR_NAME"), conn.CharacterID, stacksizeB)
            'load both stacks into the inventory
            LoadNewItem(conn, id)
            LoadNewItem(conn, id2)

        End If

    End Sub

    Public Sub JoinStacks(join As JoinStackRequest, conn As Connection)

        'get item count and ITEMBASE ID for each stack, also retrieve the name of the item
        Dim sSql1 As String = "SELECT a.INT_COUNT, b.STR_NAME, b.ID_ITEMBASE FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE ID_ITEM='" & join.INT_ID_A & "' AND BYTE_LOCATION='" & ItemLocation.Inventory & "';"
        Dim sSql2 As String = "SELECT a.INT_COUNT, b.ID_ITEMBASE FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE ID_ITEM='" & join.INT_ID_B & "' AND BYTE_LOCATION='" & ItemLocation.Inventory & "';"

        Dim row1 As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql1)
        Dim row2 As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql2)

        If row1 Is Nothing Or row2 Is Nothing Then Exit Sub
        If row1.Count = 0 Or row2.Count = 0 Then Exit Sub
        If row1("ID_ITEMBASE") = row2("ID_ITEMBASE") Then

            'get ammount in stacks A & B
            Dim count_A As Integer = row1("INT_COUNT")
            Dim count_B As Integer = row2("INT_COUNT")

            'get the total in both stacks
            Dim new_count As Integer = count_A + count_B

            'delete the 2 old stacks
            sSql1 = "UPDATE TBL_ITEMS SET BYTE_LOCATION='" & ItemLocation.Deleted & "' WHERE ID_ITEM='" & join.INT_ID_A & "';"
            sSql2 = "UPDATE TBL_ITEMS SET BYTE_LOCATION='" & ItemLocation.Deleted & "' WHERE ID_ITEM='" & join.INT_ID_B & "';"
            DB.GameDB.ExecuteNonQuery(sSql1)
            DB.GameDB.ExecuteNonQuery(sSql2)

            'send an ItemRemove packet for each stack
            RemoveItem(join.INT_ID_A, conn)
            RemoveItem(join.INT_ID_B, conn)

            System.Windows.Forms.Application.DoEvents()

            'create one new stack with the combined ammount in it
            Dim new_id As Int64 = CreateNewItem(row1("STR_NAME"), conn.CharacterID, new_count)
            'load the new item into the players inventory
            LoadNewItem(conn, new_id)

        End If

    End Sub

    Public Sub UseItem(id As Int64, conn As Connection)

        If Not conn.IsAlive Then Exit Sub

        'query the database for the item info we need based on id, make sure it is in the inventory
        Dim sSql As String = "SELECT b.INT_STDITEM, b.INT2_LEVELREQ, b.BOOL_STACKS, b.BYTE_TYPE, b.INT_SHAPE, b.STR_NAME, a.INT_COUNT FROM TBL_ITEMS a JOIN TBL_ITEMBASE b ON a.ID_ITEMBASE = b.ID_ITEMBASE WHERE a.ID_ITEM=" & id & " AND BYTE_LOCATION=" & ItemLocation.Inventory & ";"
        Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

        If row Is Nothing Then Exit Sub
        If row.Count = 0 Then Exit Sub

        'Is the item equipable
        If row("BYTE_TYPE") = ItemType.Bracer Or _
            row("BYTE_TYPE") = ItemType.FArmor Or _
            row("BYTE_TYPE") = ItemType.Helmet Or _
            row("BYTE_TYPE") = ItemType.HorseArmor Or _
            row("BYTE_TYPE") = ItemType.MArmor Or _
            row("BYTE_TYPE") = ItemType.Necklace Or _
            row("BYTE_TYPE") = ItemType.Ring Or _
            row("BYTE_TYPE") = ItemType.Shoes Or _
            row("BYTE_TYPE") = ItemType.Talisman Or _
            row("BYTE_TYPE") = ItemType.Torch Or _
            row("BYTE_TYPE") = ItemType.Trinket Or _
            row("BYTE_TYPE") = ItemType.Weapon Then

            'struct to hold location update info
            Dim struct As ItemLocationInfo
            'set update info itemid
            struct.INT_ID = id

            'determine the correct equip slot and set it
            Select Case CType(row("BYTE_TYPE"), ItemType)

                Case ItemType.Bracer

                    If conn.GetValue(Constants.SysVarName_EquipBracerFlag) Is Nothing Then conn.SetValue(Constants.SysVarName_EquipBracerFlag, True)

                    If conn.GetValue(Constants.SysVarName_EquipBracerFlag) Then
                        struct.location = ItemLocation.EquipLeftBracer
                        conn.SetValue(Constants.SysVarName_EquipBracerFlag, False)
                    Else
                        struct.location = ItemLocation.EquipRightBracer
                        conn.SetValue(Constants.SysVarName_EquipBracerFlag, True)
                    End If


                Case ItemType.Ring

                    If conn.GetValue(Constants.SysVarName_EquipRingFlag) Is Nothing Then conn.SetValue(Constants.SysVarName_EquipRingFlag, True)

                    If conn.GetValue(Constants.SysVarName_EquipRingFlag) Then
                        struct.location = ItemLocation.EquipLeftRing
                        conn.SetValue(Constants.SysVarName_EquipRingFlag, False)
                    Else
                        struct.location = ItemLocation.EquipRightRing
                        conn.SetValue(Constants.SysVarName_EquipRingFlag, True)
                    End If

                Case ItemType.MArmor, ItemType.FArmor
                    struct.location = ItemLocation.EquipArmor

                Case ItemType.Helmet
                    struct.location = ItemLocation.EquipHelmet

                Case ItemType.HorseArmor
                    struct.location = ItemLocation.EquipHorseArmor

                Case ItemType.Necklace
                    struct.location = ItemLocation.EquipNecklace

                Case ItemType.Shoes
                    struct.location = ItemLocation.EquipShoes

                Case ItemType.Talisman
                    struct.location = ItemLocation.EquipTalisman

                Case ItemType.Torch
                    struct.location = ItemLocation.EquipTorch

                Case ItemType.Trinket
                    struct.location = ItemLocation.EquipTrinket

                Case ItemType.Weapon
                    struct.location = ItemLocation.EquipWeapon

                Case Else
                    Output.AddLine(Constants.SysCmdAttention & "\F7UseItem() Error, unknown item type in use->equip branch\F0")
                    Exit Sub

            End Select

            'remove the item from the bag
            RemoveItem(id, conn, True)
            'update the item location and update the client
            ChangeItemLocation(struct, conn)

            'Is the item an stditem type
        ElseIf row("BYTE_TYPE") = ItemType.Liquor Or _
            row("BYTE_TYPE") = ItemType.Potion Or _
            row("BYTE_TYPE") = ItemType.Scroll Then

            If row("BYTE_TYPE") = ItemType.Liquor Or _
                row("BYTE_TYPE") = ItemType.Potion Or _
                row("BYTE_TYPE") = ItemType.Scroll Then

                'remove the stack from the players inventory
                RemoveItem(id, conn)

                'make sure the stack doesnt have a count of 0
                If Not row("BOOL_STACKS") Or row("INT_COUNT") > 0 Then

                    'set the sys var for the item id
                    conn.SetValue(Constants.SysVarName_STDItemID, id)
                    'run the function for this stditem
                    ServerScripting.Scripts.RunCommand("stditem.txt", "@" & row("INT_STDITEM"), conn)

                    'check if this item is actually a stack
                    If row("BOOL_STACKS") Then

                        'delete the stack if there is only 1 left (which has just been used)
                        If row("INT_COUNT") = 1 Then
                            sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Deleted & " WHERE ID_ITEM=" & id & ";"
                            DB.GameDB.ExecuteNonQuery(sSql)
                        Else
                            'update the stack count if there are items left in it
                            sSql = "UPDATE TBL_ITEMS SET INT_COUNT=" & (CInt(row("INT_COUNT")) - 1) & " WHERE ID_ITEM=" & id & ";"
                            DB.GameDB.ExecuteNonQuery(sSql)
                            'reload the stack into the inventory
                            LoadNewItem(conn, id)
                        End If

                    End If

                End If

                'TODO: Code multi use useitem()

                'ElseIf row("BYTE_TYPE") = ItemType.SomeTypeThatIsMultiUse then

                'multi use item code
            End If

        ElseIf row("BYTE_TYPE") = ItemType.SorcererBook Or row("BYTE_TYPE") = ItemType.TaoistBook Or row("BYTE_TYPE") = ItemType.WarriorBook Then

            Dim isForPlayersClass As Boolean

            Select Case conn.PlayerJob

                Case CharacterJobs.Warrior
                    If row("BYTE_TYPE") = ItemType.WarriorBook Then
                        isForPlayersClass = True
                    End If

                Case CharacterJobs.Taoist
                    If row("BYTE_TYPE") = ItemType.TaoistBook Then
                        isForPlayersClass = True
                    End If

                Case CharacterJobs.Sorcerer
                    If row("BYTE_TYPE") = ItemType.SorcererBook Then
                        isForPlayersClass = True
                    End If

            End Select

            If isForPlayersClass Then

                If conn.Level >= row("INT2_LEVELREQ") Then

                    Dim spellcode As Skills = row("INT_SHAPE")

                    Dim sql As String = "SELECT * FROM TBL_SKILLBOOK WHERE ID_CHARACTER=" & conn.CharacterID & " AND BYTE_SKILL=" & spellcode & ";"
                    Dim checkrow As Collection = DB.GameDB.ExecuteQueryFirstRecord(sql)

                    If checkrow.Count = 0 Then

                        'remove the book from the inventory
                        RemoveItem(id, conn)

                        'create entry for skill book (learn the skill)
                        Dim cols() As String = {"ID_CHARACTER", "BYTE_SKILL", "INT8_EXP", "BYTE_LEVEL"}
                        Dim vals() As String = {conn.CharacterID, spellcode, 0, 0}
                        DB.GameDB.NewRecord("TBL_SKILLBOOK", cols, vals)

                        'delete the book
                        sSql = "UPDATE TBL_ITEMS SET BYTE_LOCATION=" & ItemLocation.Deleted & " WHERE ID_ITEM=" & id & ";"
                        DB.GameDB.ExecuteNonQuery(sSql)

                        Packets.SendSystemMessage(conn, "You learnt the skill " & row("STR_NAME") & "!")

                        LoadPlayerSkills(conn)

                    Else
                        Packets.SendSystemMessage(conn, "You can not learn a skill twice!")
                    End If

                Else
                    Packets.SendSystemMessage(conn, "You can not learn that skill yet!")
                End If

            Else
                Packets.SendSystemMessage(conn, "That skill is not for your class!")
            End If

        End If

    End Sub

    Public Sub RemoveItem(id As Int64, conn As Connection, Optional skipweight As Boolean = False)

        'send an ItemRemove packet for each stack
        Dim pkt As Packet
        pkt.PacketType = GamePacketType.RemoveItem
        pkt.PacketOpCode = PacketOpCode.Notify
        pkt.Username = conn.Username

        Socket.SockServer.SendData(Protocol.MakePacket(pkt, id, conn.Crypto), conn.Index)

        Dim struct As ItemInfo = ItemInfoFromItemID(id)

        If Not skipweight Then



            conn.PlayerWeight.INT4_BAGWEIGHT -= struct.Base.INT2_WEIGHT * struct.INT_COUNT
            UpdatePlayerWeights(conn)

        End If

    End Sub

    Public Sub AddItemStatsToConn(ByRef conn As SocketServer.Connection, item As ItemInfo)

        conn.Stats.INT1_ACCURACY += item.Base.Stats.INT1_ACCURACY + item.AddedStats.INT1_ACCURACY
        conn.Stats.INT1_AGILITY += item.Base.Stats.INT1_AGILITY + item.AddedStats.INT1_AGILITY
        conn.Stats.INT1_VELOCITY += item.Base.Stats.INT1_VELOCITY + item.AddedStats.INT1_VELOCITY
        conn.Stats.INT1_LUCK += item.Base.Stats.INT1_LUCK + item.AddedStats.INT1_LUCK

        conn.Stats.INT2_ELEMAC_DARK += item.Base.Stats.INT2_ELEMAC_DARK + item.AddedStats.INT2_ELEMAC_DARK
        conn.Stats.INT2_ELEMAC_FIRE += item.Base.Stats.INT2_ELEMAC_FIRE + item.AddedStats.INT2_ELEMAC_FIRE
        conn.Stats.INT2_ELEMAC_HOLY += item.Base.Stats.INT2_ELEMAC_HOLY + item.AddedStats.INT2_ELEMAC_HOLY
        conn.Stats.INT2_ELEMAC_ICE += item.Base.Stats.INT2_ELEMAC_ICE + item.AddedStats.INT2_ELEMAC_ICE
        conn.Stats.INT2_ELEMAC_LIGHT += item.Base.Stats.INT2_ELEMAC_LIGHT + item.AddedStats.INT2_ELEMAC_LIGHT
        conn.Stats.INT2_ELEMAC_PHANTOM += item.Base.Stats.INT2_ELEMAC_PHANTOM + item.AddedStats.INT2_ELEMAC_PHANTOM
        conn.Stats.INT2_ELEMAC_WIND += item.Base.Stats.INT2_ELEMAC_WIND + item.AddedStats.INT2_ELEMAC_WIND

        conn.Stats.INT2_ELEMC_DARK += item.Base.Stats.INT2_ELEMC_DARK + item.AddedStats.INT2_ELEMC_DARK
        conn.Stats.INT2_ELEMC_FIRE += item.Base.Stats.INT2_ELEMC_FIRE + item.AddedStats.INT2_ELEMC_FIRE
        conn.Stats.INT2_ELEMC_HOLY += item.Base.Stats.INT2_ELEMC_HOLY + item.AddedStats.INT2_ELEMC_HOLY
        conn.Stats.INT2_ELEMC_ICE += item.Base.Stats.INT2_ELEMC_ICE + item.AddedStats.INT2_ELEMC_ICE
        conn.Stats.INT2_ELEMC_LIGHT += item.Base.Stats.INT2_ELEMC_LIGHT + item.AddedStats.INT2_ELEMC_LIGHT
        conn.Stats.INT2_ELEMC_PHANTOM += item.Base.Stats.INT2_ELEMC_PHANTOM + item.AddedStats.INT2_ELEMC_PHANTOM
        conn.Stats.INT2_ELEMC_WIND += item.Base.Stats.INT2_ELEMC_WIND + item.AddedStats.INT2_ELEMC_WIND

        conn.Stats.INT2_MAX_AC += item.Base.Stats.INT2_MAX_AC + item.AddedStats.INT2_MAX_AC
        conn.Stats.INT2_MAX_MAC += item.Base.Stats.INT2_MAX_MAC + item.AddedStats.INT2_MAX_MAC
        conn.Stats.INT2_MAX_DC += item.Base.Stats.INT2_MAX_DC + item.AddedStats.INT2_MAX_DC
        conn.Stats.INT2_MAX_SC += item.Base.Stats.INT2_MAX_SC + item.AddedStats.INT2_MAX_SC
        conn.Stats.INT2_MAX_MC += item.Base.Stats.INT2_MAX_MC + item.AddedStats.INT2_MAX_MC

        conn.Stats.INT2_MIN_AC += item.Base.Stats.INT2_MIN_AC + item.AddedStats.INT2_MIN_AC
        conn.Stats.INT2_MIN_MAC += item.Base.Stats.INT2_MIN_MAC + item.AddedStats.INT2_MIN_MAC
        conn.Stats.INT2_MIN_DC += item.Base.Stats.INT2_MIN_DC + item.AddedStats.INT2_MIN_DC
        conn.Stats.INT2_MIN_SC += item.Base.Stats.INT2_MIN_SC + item.AddedStats.INT2_MIN_SC
        conn.Stats.INT2_MIN_MC += item.Base.Stats.INT2_MIN_MC + item.AddedStats.INT2_MIN_MC

    End Sub

    Public Sub RemoveItemStatsFromConn(ByRef conn As SocketServer.Connection, item As ItemInfo)

        conn.Stats.INT1_ACCURACY -= (item.Base.Stats.INT1_ACCURACY + item.AddedStats.INT1_ACCURACY)
        conn.Stats.INT1_AGILITY -= (item.Base.Stats.INT1_AGILITY + item.AddedStats.INT1_AGILITY)
        conn.Stats.INT1_VELOCITY -= (item.Base.Stats.INT1_VELOCITY + item.AddedStats.INT1_VELOCITY)
        conn.Stats.INT1_LUCK -= (item.Base.Stats.INT1_LUCK + item.AddedStats.INT1_LUCK)

        conn.Stats.INT2_ELEMAC_DARK -= (item.Base.Stats.INT2_ELEMAC_DARK + item.AddedStats.INT2_ELEMAC_DARK)
        conn.Stats.INT2_ELEMAC_FIRE -= (item.Base.Stats.INT2_ELEMAC_FIRE + item.AddedStats.INT2_ELEMAC_FIRE)
        conn.Stats.INT2_ELEMAC_HOLY -= (item.Base.Stats.INT2_ELEMAC_HOLY + item.AddedStats.INT2_ELEMAC_HOLY)
        conn.Stats.INT2_ELEMAC_ICE -= (item.Base.Stats.INT2_ELEMAC_ICE + item.AddedStats.INT2_ELEMAC_ICE)
        conn.Stats.INT2_ELEMAC_LIGHT -= (item.Base.Stats.INT2_ELEMAC_LIGHT + item.AddedStats.INT2_ELEMAC_LIGHT)
        conn.Stats.INT2_ELEMAC_PHANTOM -= (item.Base.Stats.INT2_ELEMAC_PHANTOM + item.AddedStats.INT2_ELEMAC_PHANTOM)
        conn.Stats.INT2_ELEMAC_WIND -= (item.Base.Stats.INT2_ELEMAC_WIND + item.AddedStats.INT2_ELEMAC_WIND)

        conn.Stats.INT2_ELEMC_DARK -= (item.Base.Stats.INT2_ELEMC_DARK + item.AddedStats.INT2_ELEMC_DARK)
        conn.Stats.INT2_ELEMC_FIRE -= (item.Base.Stats.INT2_ELEMC_FIRE + item.AddedStats.INT2_ELEMC_FIRE)
        conn.Stats.INT2_ELEMC_HOLY -= (item.Base.Stats.INT2_ELEMC_HOLY + item.AddedStats.INT2_ELEMC_HOLY)
        conn.Stats.INT2_ELEMC_ICE -= (item.Base.Stats.INT2_ELEMC_ICE + item.AddedStats.INT2_ELEMC_ICE)
        conn.Stats.INT2_ELEMC_LIGHT -= (item.Base.Stats.INT2_ELEMC_LIGHT + item.AddedStats.INT2_ELEMC_LIGHT)
        conn.Stats.INT2_ELEMC_PHANTOM -= (item.Base.Stats.INT2_ELEMC_PHANTOM + item.AddedStats.INT2_ELEMC_PHANTOM)
        conn.Stats.INT2_ELEMC_WIND -= (item.Base.Stats.INT2_ELEMC_WIND + item.AddedStats.INT2_ELEMC_WIND)

        conn.Stats.INT2_MAX_AC -= (item.Base.Stats.INT2_MAX_AC + item.AddedStats.INT2_MAX_AC)
        conn.Stats.INT2_MAX_MAC -= (item.Base.Stats.INT2_MAX_MAC + item.AddedStats.INT2_MAX_MAC)
        conn.Stats.INT2_MAX_DC -= (item.Base.Stats.INT2_MAX_DC + item.AddedStats.INT2_MAX_DC)
        conn.Stats.INT2_MAX_SC -= (item.Base.Stats.INT2_MAX_SC + item.AddedStats.INT2_MAX_SC)
        conn.Stats.INT2_MAX_MC -= (item.Base.Stats.INT2_MAX_MC + item.AddedStats.INT2_MAX_MC)

        conn.Stats.INT2_MIN_AC -= (item.Base.Stats.INT2_MIN_AC + item.AddedStats.INT2_MIN_AC)
        conn.Stats.INT2_MIN_MAC -= (item.Base.Stats.INT2_MIN_MAC + item.AddedStats.INT2_MIN_MAC)
        conn.Stats.INT2_MIN_DC -= (item.Base.Stats.INT2_MIN_DC + item.AddedStats.INT2_MIN_DC)
        conn.Stats.INT2_MIN_SC -= (item.Base.Stats.INT2_MIN_SC + item.AddedStats.INT2_MIN_SC)
        conn.Stats.INT2_MIN_MC -= (item.Base.Stats.INT2_MIN_MC + item.AddedStats.INT2_MIN_MC)

    End Sub

End Module
